#include "uart_comm.h"
#include <string.h>
#include <stdbool.h>
#include <stdio.h>

/*-----------------------------------------------------------------
回调函数集成（在stm32fXXxx_it.c中）
// USART1中断处理
void USART1_IRQHandler(void) {
	HAL_UART_IRQHandler(&huart1);
}

// USART3中断处理
void USART3_IRQHandler(void) {
	HAL_UART_IRQHandler(&huart3);
}

// DMA发送完成回调
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
	UARTCOM_ProcessTxCompleteCallback(huart);
}

// UART空闲中断回调
void HAL_UART_IdleCallback(UART_HandleTypeDef *huart) {
	UARTCOM_ProcessIdleCallback(huart);
}

// UART错误回调
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) {
	UARTCOM_ProcessErrorCallback(huart);
}
------------------------------------------------------*/

// ================ 外部硬件声明 ================
extern UART_HandleTypeDef huart1;          	// USART1 句柄
extern DMA_HandleTypeDef hdma_usart1_rx;   	// USART1 接收 DMA
extern DMA_HandleTypeDef hdma_usart1_tx;    // USART1 发送 DMA
extern UART_HandleTypeDef huart3;           // USART3 句柄
extern DMA_HandleTypeDef hdma_usart3_rx;    // USART3 接收 DMA
extern DMA_HandleTypeDef hdma_usart3_tx;    // USART3 发送 DMA

// ================ 全局资源定义 ================

/* USART1资源管理实例
 * 包含所有硬件句柄、缓冲区和队列资源
 */
UART_Resource_t usart1_resource = {
    .huart = &huart1,         	// USART1外设
    .hdma_rx = &hdma_usart1_rx, // USART1接收DMA
    .hdma_tx = &hdma_usart1_tx, // USART1发送DMA
    .current_rx_index = 0,     	// 当前接收缓冲索引(0/1)
    .tx_task_handle = NULL,   	// 发送任务句柄(初始化空)
    .tx_in_progress = false,  	// 发送状态标志(初始false)
    .rx_queue = NULL,         	// 接收队列(待初始化)
    .tx_queue = NULL          	// 发送队列(待初始化)
};

/* USART3资源管理实例
 * 配置与USART1类似
 */
UART_Resource_t usart3_resource = {
    .huart = &huart3,         	// USART3外设
    .hdma_rx = &hdma_usart3_rx, // USART3接收DMA
    .hdma_tx = &hdma_usart3_tx, // USART3发送DMA
    .current_rx_index = 0,     	// 当前接收缓冲索引
    .tx_task_handle = NULL,   	// 发送任务句柄
    .tx_in_progress = false,  	// 发送状态标志
    .rx_queue = NULL,         	// 接收队列
    .tx_queue = NULL          	// 发送队列
};

// 全局空闲帧队列(管理可用的发送帧)
osMessageQueueId_t free_frame_queue = NULL;

// ================ 本地静态资源 ================

/* 接收缓冲区
 * - 双缓冲机制: 每个串口有自己的接收池
 * - MAX_RX_BUF_SIZE 被分成两个等份
 */
static uint8_t usart1_rx_pool[MAX_RX_BUF_SIZE]; // USART1接收池
static uint8_t usart3_rx_pool[MAX_RX_BUF_SIZE]; // USART3接收池

/* 发送帧池
 * - 预先分配的发送帧缓冲区
 * - TX_POOL_SIZE: 同时支持的最大发送帧数
 * - MAX_TX_BUF_SIZE: 每个帧最大长度
 */
static uint8_t tx_frame_pool[TX_POOL_SIZE][MAX_TX_BUF_SIZE]; // 发送数据存储池
static DataFrame_t tx_frames[TX_POOL_SIZE]; // 发送帧元数据

// LoRa地址(用于特殊格式的消息)
const uint8_t lora_addr[LORA_ADDR_SIZE] = {0x00, 0x03, 0x04};

// ================ 静态函数声明 ================
static UART_Resource_t* get_resource_for_uart(UART_HandleTypeDef* huart);
static void process_echo(DataFrame_t* rx_frame, UART_Resource_t* resource);
static void process_uart_queue(UART_Resource_t* resource);//static void wait_for_transmit_complete(UART_Resource_t* resource, uint8_t* data, uint16_t len);
static void start_dma_reception(UART_Resource_t* resource);

// ================ 初始化函数 ================

/**
 * 初始化发送帧池
 * - 设置帧缓冲区指针
 * - 初始化为可用状态
 * - 添加到空闲帧队列
 */
void UARTCOM_InitBuffers(void) {
    for (int i = 0; i < TX_POOL_SIZE; i++) {
        tx_frames[i].data = tx_frame_pool[i];  // 绑定数据存储区
        tx_frames[i].length = 0;              // 初始无数据
        tx_frames[i].is_locked = false;        // 初始未锁定
        tx_frames[i].source_id = 0;            // 初始源ID
        tx_frames[i].add_lora = false;         // 初始不添加LoRa
        
        DataFrame_t* frame_ptr = &tx_frames[i];
        osMessageQueuePut(free_frame_queue, &frame_ptr, 0, 0); // 添加到空闲队列
    }
}

/**
 * 初始化UART资源
 * @param resource 要初始化的UART资源指针
 * 
 * - 分配接收缓冲区
 * - 启用空闲中断
 * - 启动DMA接收
 */
void UARTCOM_InitUARTResource(UART_Resource_t* resource) {
    // 选择当前UART的接收池
    uint8_t* buffer_base = (resource->huart == &huart1) ? 
                           usart1_rx_pool : usart3_rx_pool;
    
    // 初始化双缓冲区
    for (int i = 0; i < 2; i++) {
        resource->rx_frames[i].data = buffer_base + (i * (MAX_RX_BUF_SIZE/2));
        resource->rx_frames[i].length = 0;
        resource->rx_frames[i].is_locked = false;
    }
    
    // 启用空闲中断并启动DMA接收
    __HAL_UART_ENABLE_IT(resource->huart, UART_IT_IDLE);
    HAL_UART_Receive_DMA(resource->huart, resource->rx_frames[resource->current_rx_index].data, MAX_RX_BUF_SIZE/2);
	
	resource->tx_sem = osSemaphoreNew(1, 0, NULL);  // 二值信号量
}

// ================ 帧管理API ================

/**
 * 从空闲队列获取发送帧
 * @param timeout 超时时间(ms)
 * @return 成功返回帧指针，失败返回NULL
 * 
 * - 从空闲帧队列获取帧
 * - 设置锁定状态防止重复使用
 */
DataFrame_t* UARTCOM_AcquireTxFrame(uint32_t timeout) {
    DataFrame_t* frame_ptr = NULL;
    if (osMessageQueueGet(free_frame_queue, &frame_ptr, NULL, timeout) == osOK && frame_ptr) {
        frame_ptr->is_locked = true; // 锁定帧
        return frame_ptr;
    }
    return NULL; // 超时或失败
}

/**
 * 释放发送帧资源
 * @param frame 要释放的帧指针
 * 
 * - 重置帧状态
 * - 返回空闲队列
 */
void UARTCOM_ReleaseTxFrame(DataFrame_t* frame) {
    if (frame) {
        frame->length = 0;        // 清除数据长度
        frame->is_locked = false; // 解除锁定
        DataFrame_t* frame_ptr = frame;
        osMessageQueuePut(free_frame_queue, &frame_ptr, 0, 0); // 归还队列
    }
}

// ================ 核心通信功能 ================

/**
 * 发送消息到指定UART
 * @param msg 文本消息
 * @param resource 目标UART资源
 * @param add_lora 是否添加LoRa地址
 * @param source_id 源标识符(0-255)
 * 
 * - 构建增强帧(头+数据+尾)
 * - 处理消息过长的情况
 * - 将帧加入发送队列
 */
void UARTCOM_SendToUART(const char* msg, UART_Resource_t* resource, bool add_lora, uint8_t source_id) {
    // 检查队列空间
    if (osMessageQueueGetSpace(resource->tx_queue) == 0) {
        return; // 队列满，丢弃消息
    }
	
    // 获取发送帧(带超时)
    DataFrame_t* frame = UARTCOM_AcquireTxFrame(FRAME_ACQUIRE_TIMEOUT);
    if (!frame) return; // 获取失败
    
    // 设置帧参数
    frame->source_id = source_id;
    frame->add_lora = add_lora;
    
    uint16_t data_len = strlen(msg); // 原始数据长度
    
    // 构建增强帧头
    uint8_t frame_header[FRAME_HEADER_SIZE] = {
        FRAME_START_MARKER_1,     // 帧起始标记1
        FRAME_START_MARKER_2,     // 帧起始标记2
        source_id,                // 源ID
        (uint8_t)(data_len & 0xFF), // 长度低字节
        (uint8_t)(data_len >> 8)   // 长度高字节
    };
    
    // 构建帧尾(CRLF)
    uint8_t frame_footer[FRAME_FOOTER_SIZE] = {
        FRAME_END_MARKER_CR,      // 回车符
        FRAME_END_MARKER_LF       // 换行符
    };
    
    // 检查帧长度限制
    uint16_t total_len = FRAME_HEADER_SIZE + data_len + FRAME_FOOTER_SIZE;
    if (total_len > MAX_TX_BUF_SIZE) {
        // 替换为错误消息
        const char* error_msg = "MSG TOO LONG";
        data_len = strlen(error_msg);
        total_len = FRAME_HEADER_SIZE + data_len + FRAME_FOOTER_SIZE;
        memcpy(frame->data + FRAME_HEADER_SIZE, error_msg, data_len);
    } else {
        // 正常数据复制
        memcpy(frame->data + FRAME_HEADER_SIZE, msg, data_len);
    }
    
    // 构建完整帧
    memcpy(frame->data, frame_header, FRAME_HEADER_SIZE);                      // 帧头
    memcpy(frame->data + FRAME_HEADER_SIZE + data_len, frame_footer, FRAME_FOOTER_SIZE); // 帧尾
    
    // 设置帧元数据
    frame->length = total_len;                            // 总长度
    frame->last_sent_time = osKernelGetTickCount();       // 时间戳
    
    // 加入发送队列(失败则释放帧)
    if (osMessageQueuePut(resource->tx_queue, &frame, 0, 100) != osOK) {
        UARTCOM_ReleaseTxFrame(frame);
    }
}

// ================ 任务函数 ================

/**
 * UART接收任务(处理所有串口)
 * @param argument 未使用
 * 
 * - 循环处理两个串口的接收队列
 * - 每隔10ms轮询一次
 */
void UARTCOM_ReceiveTask(void* argument) {
    (void)argument;
    while(1) {
        process_uart_queue(&usart1_resource); // 处理USART1
        process_uart_queue(&usart3_resource); // 处理USART3
        osDelay(10); // 适当释放CPU
    }
}

/**
 * UART发送任务(每个串口独立)
 * @param argument 指向UART资源的指针
 * 
 * - 处理指定串口的发送队列
 * - 计算帧间隔防止粘包
 * - 构建最终数据并发送
 */
void UARTCOM_TransmitTask(void* argument) {
    UART_Resource_t* resource = (UART_Resource_t*)argument;
    resource->tx_task_handle = osThreadGetId(); // 保存任务句柄(用于唤醒)
    
    DataFrame_t* tx_frame;          // 当前发送帧
    uint32_t last_sent_time = 0;     // 上次发送时间
    
    while(1) {
        // 从发送队列获取帧(阻塞等待)
        if (osMessageQueueGet(resource->tx_queue, &tx_frame, NULL, portMAX_DELAY) == osOK) {
            // 计算最小帧间隔(防止粘包)
            uint32_t baudrate = resource->huart->Init.BaudRate;
            uint32_t bits_per_frame = (tx_frame->length * 10);  // 10位/字节
            uint32_t min_frame_interval_us = (bits_per_frame * 1000000) / baudrate;
            min_frame_interval_us = (min_frame_interval_us * 13) / 10;  // 增加30%余量
            uint32_t min_interval_ms = (min_frame_interval_us + 999) / 1000;
            
            // 等待达到最小间隔要求
            while ((osKernelGetTickCount() - last_sent_time) < min_interval_ms) {
                osDelay(1);
            }
            
            // 构建最终数据(考虑LoRa地址)
            uint8_t final_data[MAX_TX_BUF_SIZE + LORA_ADDR_SIZE]; // 最终发送数据
            uint16_t final_len = 0;                             // 最终长度
            
            if (tx_frame->add_lora) {
                memcpy(final_data, lora_addr, LORA_ADDR_SIZE); // 添加LoRa地址
                memcpy(final_data + LORA_ADDR_SIZE, tx_frame->data, tx_frame->length);
                final_len = LORA_ADDR_SIZE + tx_frame->length;
            } else {
                memcpy(final_data, tx_frame->data, tx_frame->length); // 直接复制
                final_len = tx_frame->length;
            }
            
            // 发送数据(带重试机制)
            if (final_len > 0) {
                resource->tx_in_progress = true; // 标记发送中
                HAL_StatusTypeDef status;
                uint8_t retry_count = 0;
                
                do { // 尝试发送(最多重试10次)
                    status = HAL_UART_Transmit_DMA(resource->huart, final_data, final_len);
                    if (status == HAL_BUSY) {
                        osDelay(1);
                        retry_count++;
                    }
                } while (status == HAL_BUSY && retry_count < 10);
                
                // 等待发送完成
                if (status == HAL_OK) {
                    // 等待信号量（代替轮询）
                    osSemaphoreAcquire(resource->tx_sem, osWaitForever);
                }
            }
            
            // 更新状态并释放帧
            last_sent_time = osKernelGetTickCount();
            UARTCOM_ReleaseTxFrame(tx_frame);
        }
    }
}

// ================ 中断回调处理 ================

/**
 * 空闲中断处理函数
 * @param huart 触发中断的UART句柄
 * 
 * - 停止当前DMA
 * - 计算接收字节数
 * - 将完整帧加入接收队列
 * - 切换接收缓冲区
 * - 重启接收
 */
void UARTCOM_ProcessIdleCallback(UART_HandleTypeDef* huart) {
    // 获取对应的资源结构
    UART_Resource_t* resource = get_resource_for_uart(huart);
    if (!resource) return;
    
    // 停止当前DMA传输
    HAL_UART_DMAStop(huart);
    
    // 计算接收字节数
    uint16_t received_bytes = (MAX_RX_BUF_SIZE/2) - __HAL_DMA_GET_COUNTER(resource->hdma_rx);
    
    // 处理接收数据
    if (received_bytes > 0) {
        // 设置帧长度并加入接收队列
        resource->rx_frames[resource->current_rx_index].length = received_bytes;
        DataFrame_t* frame = &resource->rx_frames[resource->current_rx_index];
        osMessageQueuePut(resource->rx_queue, &frame, 0, 0);
    }
    
    // 切换缓冲区并重启接收
    resource->current_rx_index = (resource->current_rx_index + 1) % 2;
    start_dma_reception(resource);
}

/**
 * 错误中断处理函数
 * @param huart 触发错误的UART句柄
 * 
 * - 清除所有错误标志
 * - 重启DMA接收
 */
void UARTCOM_ProcessErrorCallback(UART_HandleTypeDef* huart) {
    UART_Resource_t* resource = get_resource_for_uart(huart);
    if (!resource) return;
    
    // 清除UART错误标志
    __HAL_UART_CLEAR_FLAG(huart, UART_FLAG_PE | UART_FLAG_FE | UART_FLAG_NE | UART_FLAG_ORE);
    
    // 重启接收
    start_dma_reception(resource);
}

/**
 * 发送完成处理函数
 * @param huart 完成发送的UART句柄
 * 
 * - 清除发送中标志
 * - 唤醒发送任务(如果存在)
 */
void UARTCOM_ProcessTxCompleteCallback(UART_HandleTypeDef* huart) {
    UART_Resource_t* resource = get_resource_for_uart(huart);
    if (resource && resource->tx_in_progress) {
        resource->tx_in_progress = false;
		osSemaphoreRelease(resource->tx_sem);
    }
}

// ================ 静态函数实现 ================

/**
 * 获取UART对应的资源结构
 * @param huart UART句柄
 * @return 匹配的资源结构指针
 */
static UART_Resource_t* get_resource_for_uart(UART_HandleTypeDef* huart) {
    if (huart->Instance == USART1) return &usart1_resource;
    if (huart->Instance == USART3) return &usart3_resource;
    return NULL;
}

/**
 * 启动DMA接收
 * @param resource UART资源指针
 * 
 * - 重新配置并启用DMA
 * - 设置到当前接收缓冲区
 */
static void start_dma_reception(UART_Resource_t* resource) {
    __HAL_DMA_DISABLE(resource->hdma_rx);  // 禁用DMA
    __HAL_DMA_CLEAR_FLAG(resource->hdma_rx, DMA_FLAG_TCIF0_4); // 清除传输完成标志
    
    // 启动新接收
    HAL_UART_Receive_DMA(resource->huart, resource->rx_frames[resource->current_rx_index].data, MAX_RX_BUF_SIZE/2);
}

/**
 * 处理接收数据(回显)
 * @param rx_frame 接收帧指针
 * @param resource UART资源指针
 * 
 * - 构建调试信息字符串
 * - 显示HEX和ASCII格式
 * - 分发到对应串口
 */
static void process_echo(DataFrame_t* rx_frame, UART_Resource_t* resource) {
    char full_msg[256]; // 消息缓冲区
    int msg_pos = 0;    // 当前写入位置
    
    // 添加基本信息头
    msg_pos += snprintf(full_msg + msg_pos, sizeof(full_msg) - msg_pos,
                       "\r\nU%d Recv %u bytes:",
                       (resource->huart->Instance == USART1) ? 1 : 3,
                       rx_frame->length);
    
    // HEX数据部分(最多显示20字节)
    msg_pos += snprintf(full_msg + msg_pos, sizeof(full_msg) - msg_pos, " HEX[");
    uint16_t display_len = MIN(rx_frame->length, 20);
    for (int i = 0; i < display_len; i++) {
        if (msg_pos + 5 < sizeof(full_msg)) { // 边界检查
            msg_pos += snprintf(full_msg + msg_pos, sizeof(full_msg) - msg_pos, 
                               "%02X ", rx_frame->data[i]);
        }
    }
    
    // ASCII数据部分
    msg_pos += snprintf(full_msg + msg_pos, sizeof(full_msg) - msg_pos, "] ASCII[");
    for (int i = 0; i < display_len; i++) {
        if (msg_pos < sizeof(full_msg) - 2) {
            uint8_t c = rx_frame->data[i];
            full_msg[msg_pos++] = (c >= 0x20 && c <= 0x7E) ? c : '.'; // 可打印字符或点号
        }
    }
    
    // 添加结束符
    msg_pos += snprintf(full_msg + msg_pos, sizeof(full_msg) - msg_pos, "]\r\n");
    full_msg[MIN(msg_pos, sizeof(full_msg) - 1)] = '\0'; // 安全截断
    
    // 分发回显消息(基于串口类型)
    if (resource->huart->Instance == USART1) {
        // USART1接收的数据只回显到USART1
        UARTCOM_SendToUART(full_msg, &usart1_resource, false, 0xEE);
    } else if (resource->huart->Instance == USART3) {
        // USART3接收的数据回显到USART1和USART3
        UARTCOM_SendToUART(full_msg, &usart3_resource, true, 0xEE); // USART3带LoRa
        UARTCOM_SendToUART(full_msg, &usart1_resource, false, 0xEE); // USART1普通
    }
}

/**
 * 处理UART接收队列
 * @param resource UART资源指针
 * 
 * - 从接收队列获取帧
 * - 调用回显处理函数
 */
static void process_uart_queue(UART_Resource_t* resource) {
    DataFrame_t* rx_frame;
    if (osMessageQueueGet(resource->rx_queue, &rx_frame, NULL, 0) == osOK) {
        process_echo(rx_frame, resource); // 处理接收帧
        // 添加帧重置
        rx_frame->length = 0;
    }
}

// ================ HAL回调桥接 ================

/**
 * HAL发送完成回调
 * 连接HAL库和自定义处理函数
 */
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
    UARTCOM_ProcessTxCompleteCallback(huart);
}

/**
 * HAL空闲中断回调
 * 连接HAL库和自定义处理函数
 */
void HAL_UART_IdleCallback(UART_HandleTypeDef *huart) {
    UARTCOM_ProcessIdleCallback(huart);
}

/**
 * HAL错误回调
 * 连接HAL库和自定义处理函数
 */
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) {
    UARTCOM_ProcessErrorCallback(huart);
}

